#include <vtkGPUVolumeRayCastMapper.h>
#include <vtkImageStencilToImage.h>
#include <vtkAssemblyNode.h>
#include <vtkAssemblyPath.h>
#include <vtkBorderRepresentation.h>
#include <vtkBorderWidget.h>
#include <vtkCommand.h>
#include <vtkCoordinate.h>
#include <vtkImageActor.h>
#include <vtkImageMapper3D.h>
#include <vtkInteractorStyleImage.h>
#include <vtkTIFFReader.h>
#include <vtkPropPicker.h>
#include <vtkProperty2D.h>
#include <vtkSmartPointer.h>
#include <vtkimagedata.h>
#include <vtkStringArray.h>
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkStructuredPoints.h>
#include <vtkStructuredPointsReader.h>
#include <vtkGPUVolumeRayCastMapper.h>
#include <vtkPiecewiseFunction.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkVolumeProperty.h>
#include <vtkColorTransferFunction.h>
#include <vtkGPUVolumeRayCastMapper.h>
#include <vtkImageMask.h>
/****main****/
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkExtractVOI.h>
#include <vtkPointPicker.h>
#include <vtkCoordinate.h>
#include <vtkCallbackCommand.h>
#include <vtkProperty.h>
#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkMath.h>
#include <vtkNamedColors.h>
#include <vtkPolyLine.h>
#include <vtkBMPReader.h>
#include <vtkImageActor.h>



// 自定义交互样式类
class ROIImageInteractorStyle : public vtkInteractorStyleImage
{
public:
	static ROIImageInteractorStyle* New();
	vtkTypeMacro(ROIImageInteractorStyle, vtkInteractorStyleImage);

	ROIImageInteractorStyle()
	{
		this->StartPosition[0] = this->StartPosition[1] = 0;
		this->EndPosition[0] = this->EndPosition[1] = 0;
		this->Dragging = false;

		// 创建点选择器
		this->PointPicker = vtkSmartPointer<vtkPointPicker>::New();
		this->PointPicker->SetTolerance(0.005);

		// 创建坐标转换器
		this->Coordinate = vtkSmartPointer<vtkCoordinate>::New();

		// 创建矩形框的可视化
		this->CreateRectangleActor();
	}

	virtual void OnLeftButtonDown() override
	{
		if (this->Interactor->GetControlKey())
		{
			// Ctrl+左键进入矩形选择模式
			this->Dragging = true;
			this->Interactor->GetEventPosition(this->StartPosition);

			// 使用点选择器获取精确的起始位置
			this->PointPicker->Pick(this->StartPosition[0], this->StartPosition[1], 0,
				this->CurrentRenderer);
			double* worldStart = this->PointPicker->GetPickPosition();

			// 存储世界坐标起始点
			this->WorldStart[0] = worldStart[0];
			this->WorldStart[1] = worldStart[1];
			this->WorldStart[2] = worldStart[2];

			// 显示矩形框
			if (!this->CurrentRenderer->HasViewProp(this->RectangleActor))
			{
				this->CurrentRenderer->AddActor(this->RectangleActor);
			}

			this->UpdateRectangle(this->StartPosition[0], this->StartPosition[1],
				this->StartPosition[0], this->StartPosition[1]);

			return;
		}

		vtkInteractorStyleImage::OnLeftButtonDown();
	}

	virtual void OnMouseMove() override
	{
		if (this->Dragging)
		{
			this->Interactor->GetEventPosition(this->EndPosition);

			// 使用点选择器获取精确的结束位置
			this->PointPicker->Pick(this->EndPosition[0], this->EndPosition[1], 0,
				this->CurrentRenderer);
			double* worldEnd = this->PointPicker->GetPickPosition();

			this->WorldEnd[0] = worldEnd[0];
			this->WorldEnd[1] = worldEnd[1];
			this->WorldEnd[2] = worldEnd[2];

			this->UpdateRectangle(this->StartPosition[0], this->StartPosition[1],
				this->EndPosition[0], this->EndPosition[1]);
			this->Interactor->Render();
			return;
		}

		vtkInteractorStyleImage::OnMouseMove();
	}

	virtual void OnLeftButtonUp() override
	{
		if (this->Dragging)
		{
			this->Dragging = false;
			this->Interactor->GetEventPosition(this->EndPosition);

			// 提取ROI区域
			this->ExtractROI();

			// 移除矩形框
			this->CurrentRenderer->RemoveActor(this->RectangleActor);
			this->Interactor->Render();
			return;
		}

		vtkInteractorStyleImage::OnLeftButtonUp();
	}

	// 设置原始图像数据
	void SetImageData(vtkSmartPointer<vtkImageData> imageData)
	{
		this->ImageData = imageData;
	}

	// 设置ROI渲染器
	void SetROIRenderer(vtkSmartPointer<vtkRenderer> roiRenderer)
	{
		this->ROIRenderer = roiRenderer;
	}

private:
	int StartPosition[2];
	int EndPosition[2];
	double WorldStart[3];
	double WorldEnd[3];
	bool Dragging;
	vtkSmartPointer<vtkImageData> ImageData;
	vtkSmartPointer<vtkPointPicker> PointPicker;
	vtkSmartPointer<vtkCoordinate> Coordinate;
	vtkSmartPointer<vtkActor> RectangleActor;
	vtkSmartPointer<vtkRenderer> ROIRenderer;

	// 创建矩形框可视化
	void CreateRectangleActor()
	{
		vtkNew<vtkPolyData> polyData;
		vtkNew<vtkPoints> points;
		vtkNew<vtkCellArray> lines;

		// 创建矩形边框的四个顶点
		points->InsertNextPoint(0, 0, 0);
		points->InsertNextPoint(1, 0, 0);
		points->InsertNextPoint(1, 1, 0);
		points->InsertNextPoint(0, 1, 0);

		// 创建闭合的矩形边框
		vtkNew<vtkPolyLine> polyLine;
		polyLine->GetPointIds()->SetNumberOfIds(5);
		for (int i = 0; i < 4; i++) {
			polyLine->GetPointIds()->SetId(i, i);
		}
		polyLine->GetPointIds()->SetId(4, 0); // 闭合矩形

		lines->InsertNextCell(polyLine);

		polyData->SetPoints(points);
		polyData->SetLines(lines);

		vtkNew<vtkPolyDataMapper> mapper;
		mapper->SetInputData(polyData);

		this->RectangleActor = vtkSmartPointer<vtkActor>::New();
		this->RectangleActor->SetMapper(mapper);
		this->RectangleActor->GetProperty()->SetColor(1.0, 0.0, 0.0);
		this->RectangleActor->GetProperty()->SetLineWidth(2.0);
		this->RectangleActor->GetProperty()->SetRepresentationToWireframe();
		this->RectangleActor->GetProperty()->SetOpacity(0.8);
	}

	// 更新矩形框显示
	void UpdateRectangle(int x1, int y1, int x2, int y2)
	{
		// 将屏幕坐标转换为世界坐标
		double worldCoords[4][3];

		// 转换四个角点
		this->ScreenToWorld(x1, y1, worldCoords[0]);
		this->ScreenToWorld(x2, y1, worldCoords[1]);
		this->ScreenToWorld(x2, y2, worldCoords[2]);
		this->ScreenToWorld(x1, y2, worldCoords[3]);

		// 更新矩形框的顶点
		vtkNew<vtkPoints> points;
		for (int i = 0; i < 4; i++) {
			points->InsertNextPoint(worldCoords[i]);
		}

		vtkNew<vtkPolyData> polyData;
		polyData->SetPoints(points);

		vtkNew<vtkCellArray> lines;
		vtkNew<vtkPolyLine> polyLine;
		polyLine->GetPointIds()->SetNumberOfIds(5);
		for (int i = 0; i < 4; i++) {
			polyLine->GetPointIds()->SetId(i, i);
		}
		polyLine->GetPointIds()->SetId(4, 0);
		lines->InsertNextCell(polyLine);

		polyData->SetLines(lines);

		vtkNew<vtkPolyDataMapper> mapper;
		mapper->SetInputData(polyData);
		this->RectangleActor->SetMapper(mapper);
	}

	// 屏幕坐标到世界坐标的精确转换
	void ScreenToWorld(int screenX, int screenY, double world[3])
	{
		this->Coordinate->SetCoordinateSystemToDisplay();
		this->Coordinate->SetValue(screenX, screenY, 0);
		double* worldPos = this->Coordinate->GetComputedWorldValue(this->CurrentRenderer);

		world[0] = worldPos[0];
		world[1] = worldPos[1];
		world[2] = worldPos[2];
	}

	// 世界坐标到图像索引坐标的转换
	void WorldToImageIndex(double world[3], int imageIndex[2], int dims[3])
	{
		if (!this->ImageData) return;

		// 获取图像数据的边界和间距
		double bounds[6];
		this->ImageData->GetBounds(bounds);
		double spacing[3];
		this->ImageData->GetSpacing(spacing);
		double origin[3];
		this->ImageData->GetOrigin(origin);

		// 计算图像索引（考虑图像可能不在原点）
		imageIndex[0] = static_cast<int>((world[0] - origin[0]) / spacing[0] + 0.5);
		imageIndex[1] = static_cast<int>((world[1] - origin[1]) / spacing[1] + 0.5);

		// 确保索引在有效范围内
		imageIndex[0] = std::max(0, std::min(imageIndex[0], dims[0] - 1));
		imageIndex[1] = std::max(0, std::min(imageIndex[1], dims[1] - 1));
	}

	// 提取ROI区域
	void ExtractROI()
	{
		if (!this->ImageData || !this->ROIRenderer) return;

		int dims[3];
		this->ImageData->GetDimensions(dims);

		// 将世界坐标转换为图像索引坐标
		int startIndex[2], endIndex[2];
		this->WorldToImageIndex(this->WorldStart, startIndex, dims);
		this->WorldToImageIndex(this->WorldEnd, endIndex, dims);

		// 确保正确的矩形区域（左上角到右下角）
		int xmin = std::min(startIndex[0], endIndex[0]);
		int xmax = std::max(startIndex[0], endIndex[0]);
		int ymin = std::min(startIndex[1], endIndex[1]);
		int ymax = std::max(startIndex[1], endIndex[1]);

		// 避免零尺寸区域
		if (xmin == xmax) xmax = xmin + 1;
		if (ymin == ymax) ymax = ymin + 1;

		// 确保在图像范围内
		xmin = std::max(0, xmin);
		xmax = std::min(dims[0] - 1, xmax);
		ymin = std::max(0, ymin);
		ymax = std::min(dims[1] - 1, ymax);

		if (xmin >= xmax || ymin >= ymax) {
			std::cout << "无效的ROI区域" << std::endl;
			return;
		}

		std::cout << "ROI区域索引: X[" << xmin << ", " << xmax << "], Y[" << ymin << ", " << ymax << "]" << std::endl;
		std::cout << "ROI尺寸: " << (xmax - xmin + 1) << " x " << (ymax - ymin + 1) << " 像素" << std::endl;

		// 使用vtkExtractVOI提取感兴趣区域
		vtkNew<vtkExtractVOI> extractVOI;
		extractVOI->SetInputData(this->ImageData);
		extractVOI->SetVOI(xmin, xmax, ymin, ymax, 0, 0);
		extractVOI->Update();

		// 显示提取的ROI区域
		vtkNew<vtkImageActor> roiActor;
		roiActor->GetMapper()->SetInputConnection(extractVOI->GetOutputPort());

		// 清除之前的ROI显示并添加新的
		this->ROIRenderer->RemoveAllViewProps();
		this->ROIRenderer->AddActor(roiActor);
		this->ROIRenderer->ResetCamera();

		std::cout << "ROI提取完成!" << std::endl;

		// 输出详细的坐标转换信息
		this->PrintCoordinateConversionInfo(startIndex, endIndex, dims);
	}

	// 打印坐标转换信息
	void PrintCoordinateConversionInfo(int startIndex[2], int endIndex[2], int dims[3])
	{
		std::cout << "=== 坐标转换信息 ===" << std::endl;
		std::cout << "屏幕起点: (" << StartPosition[0] << ", " << StartPosition[1] << ")" << std::endl;
		std::cout << "屏幕终点: (" << EndPosition[0] << ", " << EndPosition[1] << ")" << std::endl;
		std::cout << "世界起点: (" << WorldStart[0] << ", " << WorldStart[1] << ", " << WorldStart[2] << ")" << std::endl;
		std::cout << "世界终点: (" << WorldEnd[0] << ", " << WorldEnd[1] << ", " << WorldEnd[2] << ")" << std::endl;
		std::cout << "图像索引起点: (" << startIndex[0] << ", " << startIndex[1] << ")" << std::endl;
		std::cout << "图像索引终点: (" << endIndex[0] << ", " << endIndex[1] << ")" << std::endl;
		std::cout << "图像尺寸: " << dims[0] << " x " << dims[1] << std::endl;
	}
};

vtkStandardNewMacro(ROIImageInteractorStyle);

int main(int argc, char* argv[])
{
	vtkNew<vtkNamedColors> colors;
	// 读取示例图像[4](@ref)
	vtkNew<vtkBMPReader> reader;
	reader->SetFileName("E:/DesktopFiles/AIW_VTK/data/lena.bmp"); // 请确保图像文件存在
	reader->Update();


	if (!reader->GetOutput() || reader->GetOutput()->GetNumberOfPoints() == 0)
	{
		// 如果文件不存在，创建一个示例图像
		vtkNew<vtkImageData> imageData;
		imageData->SetDimensions(256, 256, 1);
		imageData->AllocateScalars(VTK_UNSIGNED_CHAR, 1);

		// 创建渐变图像
		int dimensions[3];
		imageData->GetDimensions(dimensions);
		for (int y = 0; y < dimensions[1]; y++)
		{
			for (int x = 0; x < dimensions[0]; x++)
			{
				unsigned char* pixel = static_cast<unsigned char*>(imageData->GetScalarPointer(x, y, 0));
				pixel[0] = static_cast<unsigned char>((x + y) % 256);
			}
		}
		reader->SetOutput(imageData);
	}

	// 创建原始图像actor
	vtkNew<vtkImageActor> originalActor;
	originalActor->GetMapper()->SetInputConnection(reader->GetOutputPort());

	// 创建双视图渲染器
	vtkNew<vtkRenderer> originalRenderer;
	originalRenderer->AddActor(originalActor);
	originalRenderer->SetBackground(colors->GetColor3d("SlateGray").GetData());
	originalRenderer->SetViewport(0.0, 0.0, 0.5, 1.0);

	vtkNew<vtkRenderer> roiRenderer;
	roiRenderer->SetBackground(colors->GetColor3d("LightBlue").GetData());
	roiRenderer->SetViewport(0.5, 0.0, 1.0, 1.0);

	// 创建渲染窗口
	vtkNew<vtkRenderWindow> renderWindow;
	renderWindow->AddRenderer(originalRenderer);
	renderWindow->AddRenderer(roiRenderer);
	renderWindow->SetSize(1000, 500);
	renderWindow->SetWindowName("VTK精确ROI提取示例");

	// 创建交互器
	vtkNew<vtkRenderWindowInteractor> interactor;
	interactor->SetRenderWindow(renderWindow);

	// 创建并设置自定义交互样式
	vtkNew<ROIImageInteractorStyle> style;
	style->SetImageData(reader->GetOutput());
	style->SetROIRenderer(roiRenderer);
	style->SetDefaultRenderer(originalRenderer);
	style->SetCurrentRenderer(originalRenderer);
	interactor->SetInteractorStyle(style);

	// 初始渲染
	originalRenderer->ResetCamera();
	roiRenderer->ResetCamera();
	renderWindow->Render();

	// 输出操作说明
	std::cout << "=== VTK精确ROI提取示例 ===" << std::endl;
	std::cout << "操作说明:" << std::endl;
	std::cout << "1. 按住Ctrl键 + 鼠标左键拖动绘制矩形选择区域" << std::endl;
	std::cout << "2. 矩形框会精确跟随鼠标位置" << std::endl;
	std::cout << "3. 释放鼠标左键完成ROI提取" << std::endl;
	std::cout << "4. 左侧显示原始图像，右侧显示提取的ROI区域" << std::endl;
	std::cout << "5. 详细的坐标转换信息会输出到控制台" << std::endl;
	std::cout << std::endl;
	std::cout << "正常鼠标操作（无Ctrl键）:" << std::endl;
	std::cout << "  - 左键拖动: 平移图像" << std::endl;
	std::cout << "  - 右键拖动: 缩放图像" << std::endl;
	std::cout << "  - 中键拖动: 调整窗宽窗位" << std::endl;

	interactor->Start();

	return 0;
}